package fox.framework.rpc.client.invocation.proxy;

import fox.framework.rpc.common.ReflectionUtils;
import fox.framework.rpc.context.definition.RpcDefinition;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * jdk动态代理
 *
 * @author cuichao
 * @Description: JdkRpcProxy
 * @Date: create in 2021/1/15 15:50
 */
public class JdkRpcProxy extends RpcProxy implements InvocationHandler {


    public JdkRpcProxy(RpcDefinition definition) {
        super(definition);
    }

    @Override
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{getDefinition().serviceInterface()}, this);
    }

    @Override
    public Object getProxy(ClassLoader loader) {
        return Proxy.newProxyInstance(loader, new Class[]{getDefinition().serviceInterface()}, this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //equals method
        if(ReflectionUtils.isEqualsMethod(method)){
            return this.equals(args[0]);
        }
        // hashCode method
       if(ReflectionUtils.isHashCodeMethod(method)){
            return this.hashCode();
       }
       //  toString method
       if(ReflectionUtils.isToStringMethod(method)){
            return this.toString();
       }
        return getConsumeChain().doChain(proxy, method, args);
    }


    @Override
    public String toString() {
        return super.toString()+ " for proxy interface: " + getDefinition().serviceInterface();
    }

    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        }
        if (other == null) {
            return false;
        }
        JdkRpcProxy otherProxy;
        if (other instanceof JdkRpcProxy) {
            otherProxy = (JdkRpcProxy) other;
        }else if(Proxy.class.isAssignableFrom(other.getClass())){
            InvocationHandler invocation = Proxy.getInvocationHandler(other);
            if (!(invocation instanceof RpcProxy)) {
                return false;
            }
            otherProxy = (JdkRpcProxy) invocation;
        }else {
            return false;
        }
       return this == otherProxy;
    }


    @Override
    public int hashCode() {
        return super.hashCode();
    }
}
